home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / recvattach.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  15KB  |  609 lines

  1. /*
  2.  * Copyright (C) 1996,1997 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20. #include "mutt_curses.h"
  21. #include "mutt_menu.h"
  22. #include "rfc1524.h"
  23. #include "mime.h"
  24. #include "mailbox.h"
  25. #include "state.h"
  26. #include "attach.h"
  27.  
  28. #ifdef _PGPPATH
  29. #include "pgp.h"
  30. #endif
  31.  
  32. #include <ctype.h>
  33. #include <stdlib.h>
  34. #include <unistd.h>
  35. #include <sys/wait.h>
  36. #include <string.h>
  37. #include <errno.h>
  38.  
  39. static ATTACHPTR *gen_attach_list (BODY *m, int level, int compose)
  40. {
  41.   ATTACHPTR *top = NULL, *end = NULL, *new;
  42.  
  43.   while (m)
  44.   {
  45.     if (m->type == TYPEMULTIPART && m->parts)
  46.     {
  47.       if (top)
  48.     end->next = gen_attach_list (m->parts, level, compose);
  49.       else
  50.     end = top = gen_attach_list (m->parts, level, compose);
  51.       while (end->next)
  52.     end = end->next;
  53.     }
  54.     else
  55.     {
  56.       new = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR));
  57.       new->content = m;
  58.       new->level = level;
  59.  
  60.       if (top)
  61.       {
  62.         end->next = new;
  63.         end = new;
  64.       }
  65.       else
  66.         top = end = new;
  67.         
  68.       /* We don't support multipart messages in the compose menu yet */
  69.       if (!compose && m->type == TYPEMESSAGE &&
  70.         (!strcasecmp (m->subtype, "rfc822") ||
  71.         !strcasecmp (m->subtype, "news")) &&
  72.         is_multipart (m->parts))
  73.       {
  74.     end->next = gen_attach_list (m->parts, level + 1, compose);
  75.     while (end->next)
  76.       end = end->next;
  77.       }
  78.     }
  79.  
  80.     m = m->next;
  81.   }
  82.  
  83.   return (top);
  84. }
  85.  
  86. void mutt_update_tree (ATTACHPTR **idx, short idxlen)
  87. {
  88.   char buf[STRING];
  89.   char *s;
  90.   int x;
  91.  
  92.   for (x = 0; x < idxlen; x++)
  93.   {
  94.     if (2 * (idx[x]->level + 2) < sizeof (buf))
  95.     {
  96.       if (idx[x]->level)
  97.       {
  98.     s = buf + 2 * (idx[x]->level - 1);
  99.     *s++ = (idx[x]->content->next) ? '\003' : '\001';
  100.     *s++ = '\004';
  101.     *s++ = '\007';
  102.       }
  103.       else
  104.     s = buf;
  105.       *s = 0;
  106.     }
  107.  
  108.     if (idx[x]->tree)
  109.     {
  110.       if (strcmp (idx[x]->tree, buf) != 0)
  111.       {
  112.     safe_free ((void **) &idx[x]->tree);
  113.     idx[x]->tree = safe_strdup (buf);
  114.       }
  115.     }
  116.     else
  117.       idx[x]->tree = safe_strdup (buf);
  118.  
  119.     if (2 * (idx[x]->level + 2) < sizeof (buf) && idx[x]->level)
  120.     {
  121.       s = buf + 2 * (idx[x]->level - 1);
  122.       *s++ = (idx[x]->content->next) ? '\005' : '\006';
  123.       *s++ = '\006';
  124.     }
  125.   }
  126. }
  127.  
  128. ATTACHPTR **mutt_gen_attach_list (BODY *cur, short *idxlen,
  129.                           short *idxmax, int compose)
  130. {
  131.   ATTACHPTR *list, *plist;
  132.   ATTACHPTR **idx;
  133.  
  134.   plist = list = gen_attach_list (cur, 0, compose);
  135.   idx = (ATTACHPTR **) safe_malloc (sizeof (ATTACHPTR *) * (*idxmax = 5));
  136.  
  137.   for (*idxlen = 0; plist; (*idxlen)++, plist = plist->next)
  138.   {
  139.     if (*idxlen == *idxmax)
  140.       safe_realloc ((void **) &idx, sizeof (ATTACHPTR *) * (*idxmax += 5));
  141.     idx[*idxlen] = plist;
  142.   }
  143.  
  144.   mutt_update_tree (idx, *idxlen);
  145.   return (idx);
  146. }
  147.  
  148. void attach_entry (char *b, size_t blen, MUTTMENU *menu, int num)
  149. {
  150.   char t[SHORT_STRING];
  151.   char s[SHORT_STRING];
  152.   char size[SHORT_STRING];
  153.   ATTACHPTR **idx = (ATTACHPTR **) menu->data;
  154.   BODY *m;
  155.  
  156.   m = idx[num]->content;
  157.   s[0] = 0;
  158.   if (m->type == TYPEMESSAGE && (!strcasecmp ("rfc822", m->subtype) ||
  159.       !strcasecmp ("news", m->subtype)) && MsgFmt[0])
  160.     _mutt_make_string (s, sizeof (s), MsgFmt, m->hdr, M_FORCESUBJ);
  161.  
  162.   mutt_pretty_size (size, sizeof (size), m->length);
  163.   snprintf (t, sizeof (t), "[%.7s/%.10s, %.6s, %s]",
  164.         TYPE (m->type), m->subtype, ENCODING (m->encoding), size);
  165.   snprintf (b, blen, " %c %2d %-34.34s %s%s",
  166.         m->tagged ? '*' : ' ',
  167.         num + 1,
  168.         t,
  169.         idx[num]->tree ? idx[num]->tree : "",
  170.         s[0] ? s : (m->description ? m->description :
  171.             (m->filename ? m->filename : "<no description>")));
  172. }
  173.  
  174. int mutt_tag_attach (MUTTMENU *menu, int n)
  175. {
  176.   return (((ATTACHPTR **) menu->data)[n]->content->tagged = !((ATTACHPTR **) menu->data)[n]->content->tagged);
  177. }
  178.  
  179. static void mutt_query_save_attachment (FILE *fp, BODY *body)
  180. {
  181.   char buf[_POSIX_PATH_MAX], tfile[_POSIX_PATH_MAX];
  182.  
  183.   if (fp && body->filename)
  184.     strfcpy (buf, body->filename, sizeof (buf));
  185.   else
  186.     buf[0] = 0;
  187.   if (mutt_get_field ("Save to file: ", buf, sizeof (buf), M_FILE | M_CLEAR) != 0 || !buf[0])
  188.     return;
  189.   mutt_expand_path (buf, sizeof (buf));
  190.   if (mutt_check_overwrite (body->filename, buf, tfile, sizeof (tfile), 0))
  191.     return;
  192.   mutt_message ("Saving...");
  193.   if (mutt_save_attachment (fp, body, tfile, 0) == 0)
  194.     mutt_message ("Attachment saved.");
  195. }
  196.  
  197. void mutt_save_attachment_list (FILE *fp, int tag, BODY *top)
  198. {
  199.   for (; top; top = top->next)
  200.   {
  201.     if (!tag || top->tagged)
  202.       mutt_query_save_attachment (fp, top);
  203.     else if (top->parts)
  204.       mutt_save_attachment_list (fp, 1, top->parts);
  205.     if (!tag)
  206.       return;
  207.   }
  208. }
  209.  
  210. static void
  211. mutt_query_pipe_attachment (char *command, FILE *fp, BODY *body, int filter)
  212. {
  213.   char tfile[_POSIX_PATH_MAX];
  214.   char warning[STRING+_POSIX_PATH_MAX];
  215.  
  216.   if (filter)
  217.   {
  218.     snprintf (warning, sizeof (warning),
  219.           "WARNING!  You are about to overwrite %s, continue?",
  220.           body->filename);
  221.     if (mutt_yesorno (warning, M_NO) != M_YES)
  222.       return;
  223.     mutt_mktemp (tfile);
  224.   }
  225.   else
  226.     tfile[0] = 0;
  227.  
  228.   if (mutt_pipe_attachment (fp, body, command, tfile))
  229.   {
  230.     if (filter)
  231.     {
  232.       mutt_unlink (body->filename);
  233.       mutt_rename_file (tfile, body->filename);
  234.       mutt_update_encoding (body);
  235.       mutt_message ("Attachment filtered.");
  236.     }
  237.   }
  238.   else
  239.   {
  240.     if (filter && tfile[0])
  241.       mutt_unlink (tfile);
  242.   }
  243. }
  244.  
  245. static void
  246. pipe_attachment_list (char *command, FILE *fp, int tag, BODY *top, int filter)
  247. {
  248.   for (; top; top = top->next)
  249.   {
  250.     if (!tag || top->tagged)
  251.       mutt_query_pipe_attachment (command, fp, top, filter);
  252.     else if (top->parts)
  253.       pipe_attachment_list (command, fp, tag, top->parts, filter);
  254.     if (!tag)
  255.       break;
  256.   }
  257. }
  258.  
  259. void mutt_pipe_attachment_list (FILE *fp, int tag, BODY *top, int filter)
  260. {
  261.   char buf[SHORT_STRING];
  262.  
  263.   if (fp)
  264.     filter = 0; /* sanity check: we can't filter in the recv case yet */
  265.  
  266.   buf[0] = 0;
  267.   if (mutt_get_field ((filter ? "Filter through: " : "Pipe to: "),
  268.                   buf, sizeof (buf), 0) != 0 || !buf[0])
  269.     return;
  270.   mutt_expand_path (buf, sizeof (buf));
  271.   pipe_attachment_list (buf, fp, tag, top, filter);
  272. }
  273.  
  274. static void print_attachment_list (FILE *fp, int tag, BODY *top)
  275. {
  276.   for (; top; top = top->next)
  277.   {
  278.     if (!tag || top->tagged)
  279.       mutt_print_attachment (fp, top);
  280.     else if (top->parts)
  281.       mutt_print_attachment_list (fp, tag, top->parts);
  282.     if (!tag)
  283.       return;
  284.   }
  285. }
  286.  
  287. void mutt_print_attachment_list (FILE *fp, int tag, BODY *top)
  288. {
  289.   if (query_quadoption (OPT_PRINT, tag ? "Print tagged attachment(s)?" : "Print attachment?") != M_YES)
  290.     return;
  291.   print_attachment_list (fp, tag, top);
  292. }
  293.  
  294. int mutt_is_message_type (int type, char *subtype)
  295. {
  296.   if (type != TYPEMESSAGE)
  297.     return 0;
  298.   if (strcasecmp (subtype, "rfc822") == 0 || strcasecmp (subtype, "news") == 0)
  299.     return 1;
  300.   return 0;
  301. }
  302.  
  303. static void
  304. bounce_attachment_list (ADDRESS *adr, int tag, BODY *body, HEADER *hdr)
  305. {
  306.   for (; body; body = body->next)
  307.   {
  308.     if (!tag || body->tagged)
  309.     {
  310.       if (!mutt_is_message_type (body->type, body->subtype))
  311.       {
  312.     mutt_error ("You may only bounce message/rfc822 parts.");
  313.     continue;
  314.       }
  315.       body->hdr->msgno = hdr->msgno;
  316.       mutt_bounce_message (body->hdr, adr);
  317.     }
  318.     else if (body->parts)
  319.       bounce_attachment_list (adr, tag, body->parts, hdr);
  320.     if (!tag)
  321.       break;
  322.   }
  323. }
  324.  
  325. static void query_bounce_attachment (int tag, BODY *top, HEADER *hdr)
  326. {
  327.   c